﻿using System;
using System.Collections.Generic;
using UnityEngine;


namespace SG
{

    public class ObjectPoolMgr : MgrCore
    {
        #region
        private static ObjectPoolMgr m_instance;
        public static ObjectPoolMgr Instance()
        {
            if (m_instance == null)
                m_instance = new ObjectPoolMgr();// InstanceHelper.Singleton<ObjectPoolMgr>();// obj.GetOrAddComponent<SceneMgr>();
            return m_instance;
        }
        #endregion
        public void FreeObject(GameObject obj)
        {
            if (obj == null)
                return;

            obj.SetActive(false);
        }
        Dictionary<string, List<GameObject>> m_ObjPool = new Dictionary<string, List<GameObject>>();
        Dictionary<GameObject, List<GameObject>> m_ObjAssetPool = new Dictionary<GameObject, List<GameObject>>();
        void ClearNullObj()
        {
            foreach (var objList in m_ObjPool)
            {
                for (int i = 0; i < objList.Value.Count;)
                {
                    if (objList.Value[i] == null)
                        objList.Value.RemoveAt(i);
                    else
                        ++i;
                }
            }
        }

        Dictionary<AudioClip, List<AudioClip>> m_AudioClipPool = new Dictionary<AudioClip, List<AudioClip>>();
        public AudioClip GetFreeAudioClipFromPool(AudioClip clip)
        {
            if (m_AudioClipPool.ContainsKey(clip))
            {
                AudioClip obj = null;
                var pool = m_AudioClipPool[clip];
                foreach (var obj1 in pool)
                {
                    if (obj1 != null)
                    {
                        return obj1;
                    }
                }
                obj = ObjectMgr.Instance().CreateAudioClip(clip);
                pool.Add(obj);
                return obj;
            }
            var newobj = ObjectMgr.Instance().CreateAudioClip(clip);
            var objList = new List<AudioClip>();
            objList.Add(newobj);
            m_AudioClipPool.Add(clip, objList);
            return newobj;
        }
        public GameObject GetFreeObjectFromPool(GameObject asset, Transform parent)
        {
            if (m_ObjAssetPool.ContainsKey(asset))
            {
                var objPool = m_ObjAssetPool[asset];
                foreach (var obj in objPool)
                {
                    if (obj != null && !obj.activeInHierarchy)
                    {
                        if (parent != null)
                            obj.transform.SetParent(parent);
                        obj.SetActive(true);
                        return obj;
                    }
                }
                var obj1 = ObjectMgr.Instance().InstantiateObject(asset, parent);
                obj1.SetActive(true);
                objPool.Add(obj1);
                return obj1;
            }
            var newobj = ObjectMgr.Instance().InstantiateObject(asset, parent);
            var objList = new List<GameObject>();
            objList.Add(newobj);
            m_ObjAssetPool.Add(asset, objList);
            return newobj;
        }

        public GameObject GetFreeObjectFromPool(string strObjName, Transform parent = null)
        {
            if (m_ObjPool.ContainsKey(strObjName))
            {
                var objPool = m_ObjPool[strObjName];
                foreach (var obj in objPool)
                {
                    if (obj != null && !obj.activeInHierarchy)
                    {
                        if (parent != null)
                            obj.transform.SetParent(parent);
                        obj.SetActive(true);
                        return obj;
                    }
                }
            }
            return null;
        }

        public GameObject GetFreeObject(string strObjName, Transform parent = null)
        {
            ClearNullObj();
            if (m_ObjPool.ContainsKey(strObjName))
            {
                var objPool = m_ObjPool[strObjName];
                var obj = GetFreeObjectFromPool(strObjName, parent);
                if (obj == null)
                {
                    // 如果没有合适的，就创建一个新的
                    var _obj = ObjectMgr.Instance().CreateObj(strObjName, parent);
                    if (_obj)
                    {
                        if (_obj != null)
                        {
                            objPool.Add(_obj);
                        }
                        return _obj;
                    }
                }
                return obj;
            }
            m_ObjPool.Add(strObjName, new List<GameObject>());
            return GetFreeObject(strObjName, parent);
        }

        public void GetFreeObjectAysnc(string strObjName, Transform parent = null, Action<GameObject> _callBack = null)
        {
            ClearNullObj();
            if (m_ObjPool.ContainsKey(strObjName))
            {
                var objPool = m_ObjPool[strObjName];
                var obj = GetFreeObjectFromPool(strObjName, parent);
                if (obj == null)
                {
                    // 如果没有合适的，就创建一个新的
                    var _obj = ObjectMgr.Instance().CreateObj(strObjName, parent);
                    if (_obj)
                    {
                        if (_obj != null)
                        {
                            objPool.Add(_obj);
                        }
                        _callBack?.Invoke(_obj);
                        return;
                    }
                }
                _callBack?.Invoke(obj);
                return;
            }
            m_ObjPool.Add(strObjName, new List<GameObject>());
            GetFreeObjectAysnc(strObjName, parent, _callBack);
        }

        public void DoReleaseByName(string strObjName)
        {
            if (m_ObjPool.ContainsKey(strObjName))
                m_ObjPool[strObjName] = null;
        }

        public override void DoRelease()
        {
            m_ObjPool.Clear();
            m_SkillPrafabPool.Clear();
            m_StateConfig.Clear();
            base.DoRelease();
        }

        GameObject m_SkillRoot;

        public void DoClearSkillRoot()
        {
            m_SkillRoot?.StopOrDestroy();
            m_SkillRoot = null;
        }
        public Transform GetSkillRoot()
        {
            if (m_SkillRoot == null)
            {
                m_SkillRoot = new GameObject("SkillRoot");
                //Object.DontDestroyOnLoad(m_SkillRoot);
            }
            return m_SkillRoot.transform;
        }
        GameObject m_StateRoot;
        Transform GetStateRoot()
        {
            if (m_StateRoot == null)
            {
                m_StateRoot = new GameObject("StateRoot");
                //Object.DontDestroyOnLoad(m_SkillRoot);
            }
            return m_StateRoot.transform;
        }
        GameObject m_EffectRoot;
        public void ClearEffectRoot()
        {
            if (m_EffectRoot)
            {
                GameObject.Destroy(m_EffectRoot);
                m_EffectRoot = null;
            }
        }
        public Transform GetEffectRoot()
        {
            if (m_EffectRoot == null)
            {
                m_EffectRoot = new GameObject("EffectRoot");
                //Object.DontDestroyOnLoad(m_EffectRoot);
            }
            return m_EffectRoot.transform;
        }
        GameObject m_ColliderRoot;
        public void ClearColliderRoot()
        {
            if (m_ColliderRoot)
            {
                GameObject.Destroy(m_ColliderRoot);
                m_ColliderRoot = null;
            }
        }
        public Transform GetColliderRoot()
        {
            if (m_ColliderRoot == null)
            {
                m_ColliderRoot = new GameObject("ColliderRoot");
                //Object.DontDestroyOnLoad(m_EffectRoot);
            }
            return m_ColliderRoot.transform;
        }
        Dictionary<string, GameObject> m_SkillPrafabPool = new Dictionary<string, GameObject>();
        public void GetSkillPrafabsByName(string strName, Action<GameObject> callBack = null)
        {
            if (strName == "")
                return;
            GameObject obj = null;
            if (m_SkillPrafabPool.TryGetValue(strName, out obj))
            {
                if (obj != null)
                    callBack?.Invoke(obj);
                else
                    m_SkillPrafabPool.Remove(strName);
            }
            if (obj == null)
            {

                var obj2 = GetFreeObject(strName, GetSkillRoot());
                if (obj2)
                {

                    if (m_SkillPrafabPool.ContainsKey(strName))
                    {
                        if (obj2)
                            GameObject.Destroy(obj2);
                        callBack?.Invoke(m_SkillPrafabPool[strName]);
                    }
                    else
                    {
                        m_SkillPrafabPool.Add(strName, obj2);
                        callBack?.Invoke(obj2);
                    }

                };

            }
        }

        Dictionary<string, GameObject> m_StateConfig = new Dictionary<string, GameObject>();
        public void GetStateConfigByName(string strName, Action<GameObject> callBack = null)
        {
            GameObject obj = null;
            if (m_StateConfig.TryGetValue(strName, out obj))
            {
                if (obj != null)
                    callBack?.Invoke(obj);
                else
                    m_StateConfig.Remove(strName);
            }
            if (obj == null)
            {
                var obj2 = GetFreeObject(strName, GetStateRoot());//, obj2 =>
                if (obj2)
                {
                    if (m_StateConfig.ContainsKey(strName))
                    {
                        if (obj2)
                            GameObject.Destroy(obj2);
                        callBack?.Invoke(m_StateConfig[strName]);
                    }
                    else
                    {
                        m_StateConfig.Add(strName, obj2);
                        callBack?.Invoke(obj2);
                    }
                }

            }
        }
    }
}